60. Площадь многоугольника

 

Заданы координаты n последовательных вершин многоугольника. Определить его площадь.

 

Вход. Первая строка содержит количество вершин многоугольника n (3 ≤ n ≤ 50000). В следующих n строках заданы координаты его последовательных вершин xi, yi (-1000 ≤ xi, yi ≤ 1000).

 

Выход. Вывести площадь многоугольника с тремя десятичными знаками.

 

Пример входа

Пример выхода

3

0 0

0 2

2 0

2.000

 

 

РЕШЕНИЕ

геометрия

 

Анализ алгоритма

Пусть А1(x1, y1), А2(x2, y2), …, Аn(xn, yn) – координаты вершин простого (без самопересечений) многоугольника, заданные в порядке его обхода по или против часовой стрелки. Тогда его площадь вычисляется по формуле трапеций:

S =

где Аn+1(xn+1, yn+1) = А1(x1, y1). Значение суммы следует брать по модулю, так как оно может быть как положительным, так и отрицательным в зависимости от направления обхода многоугольника.

Площадь трапеции положительна при xi+1 > xi и отрицательна при xi > xi+1.

Площадь многоугольника ABCDE равна

 +  +    

 

Площадь многоугольника можно найти по формуле Сюрвейера (Surveyor):

S =  =

Пусть О(0, 0) – центр координат. Тогда площадь многоугольника равна сумме площадей треугольников OA1A2, OA2A3, OA3A4, … , OAnA1. Если треугольник ориентирован против часовой стрелки, то его площадь положительна. Если против – то отрицательна. Площадь треугольника OAiA i+1 равна

 =

 

Реализация алгоритма

Координаты точек храним в векторах x и y. То есть координаты i-ой точки будут содержаться в (x[i], y[i]).

 

#define MAX 1002

int x[MAX], y[MAX];

 

Функция findArea вычисляет площадь многоугольника по выше приведенной формуле трапеций.

 

double findArea(int *x, int *y)

{

  double s = 0;

  x[n] = x[0]; y[n] = y[0];

  for(int i = 0; i < n; i++)

    s += (y[i+1] + y[i]) * (x[i+1] - x[i]) / 2.0;

  return (s < 0) ? -s : s;

}

 

Основная часть программы. Читаем входные данные.

 

scanf("%d",&n);

for(i = 0; i < n; i++)

  scanf("%d %d",&x[i],&y[i]);

 

Вычисляем и выводим площадь многоугольника.

 

printf("%.3lf\n",findArea(x,y));

 

Реализация алгоритма формула Сюрвейера

 

#include <cstdio>

#include <cmath>

#include <vector>

using namespace std;

 

double findArea(vector<int> &x, vector<int> &y)

{

  double s = 0;

  x.push_back(x[0]); y.push_back(y[0]);

  for(int i = 0; i < x.size() - 1; i++)

    s += y[i+1] * x[i] - y[i] * x[i+1];

  return fabs(s) / 2.0;

}

 

vector<int> x, y;

int i, n, a, b;

 

int main(void)

{

  scanf("%d",&n);

  for(i = 0; i < n; i++)

  {

    scanf("%d %d",&a,&b);

    x.push_back(a);

    y.push_back(b);

  }

  printf("%.3lf\n",findArea(x,y));

  return 0;

}

 

Реализация алгоритма классы

 

#include <stdio.h>

 

class Point

{

private:

  double x, y;

public:

  Point(double x = 0, double y = 0) : x(x), y(y) {};

  double GetX()

  {

    return x;

  }

  double GetY()

  {

    return y;

  }

  // cross product

  double operator* (const Point &p)

  {

    return this->x * p.y - this->y * p.x;

  }

};

 

class Shape

{

protected:

  Point *p;

  int size;

public:

  Shape(int size = 0) : size(size)

  {

    p = new Point[size+1];

  }

  ~Shape()

  {

    delete[] p;

  }

};

 

class Polygon : public Shape

{

public:

  Polygon(int n = 0) : Shape(n)  {};

 

  void ReadPoints(void)

  {

    double x, y;

    for(int i = 0; i < size; i++)

    {

      scanf("%lf %lf",&x,&y);

      p[i] = Point(x,y);

    }

    p[size] = p[0];

  }

 

  double Area(void)

  {

    double s = 0;

    for(int i = 0; i < size; i++)

      s += p[i] * p[i+1];

    return (s < 0) ? -s/2 : s/2;

  }

};

 

int n;

 

int main(void)

{

  scanf("%d",&n);

  Polygon p(n);

  p.ReadPoints();

  printf("%.3lf\n",p.Area());

  return 0;

}